/*
 	SQLiteWrapper.cpp

 	Copyright (c) 2008 Bojan Rajkovic

 	Permission is hereby granted, free of charge, to any person obtaining a copy
 	of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
 	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 	copies of the Software, and to permit persons to whom the Software is
 	furnished to do so, subject to the following conditions:
	
 	The above copyright notice and this permission notice shall be included in
 	all copies or substantial portions of the Software.

 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 	THE SOFTWARE.
*/

#include "../include/SQLiteWrapper.h"

// constructor that takes a string that points to the database file on disk
SQLiteWrapper::SQLiteWrapper (std::string DatabaseName) {
	this->databasePath = DatabaseName;
	// try and open the database, store the instance in db.
	retval = sqlite3_open(this->databasePath.c_str(), &this->database);
	// if the return value is > 0, fail out
	if( retval > SQLITE_OK ) {
		// throw an exception that indicates we couldn't open the database
		throw SQLiteException(retval);
	}
}

// gets the last error from the database instance via sqlite3_errmsg
std::string SQLiteWrapper::GetLastError() {
	std::string retString(sqlite3_errmsg(this->database));
	return retString;
}

// check if a table exists by name
int SQLiteWrapper::TableExists(std::string TableName) {
	// query the sqlite_master table to see if the table we want exists
	int retval;
	retval = ExecuteSQL(Utility::FormatString("select count(*) from sqlite_master where type='table' and name='%s';", 
		TableName.c_str()));
	// if we get a response from sqlite, check the data we got back to see if we actually
	// got a count and if it's > 0
	if (retval == SQLITE_OK) {
		if (atoi(this->columnData.at(0).c_str()) > 0) return 1;
		else return 0;
	} else return retval;
}

// executes the sql query specified and returns the return value from sqlite
// any data returned is stored in columnData and columnHeaders
int SQLiteWrapper::ExecuteSQL(std::string SQL) {
	retval = sqlite3_get_table(
		this->database,              /* An open database */
  		SQL.c_str(),      /* SQL to be executed */
  		&result,       /* Result written to a char *[]  that this points to */
  		&nrow,             /* Number of result rows written here */
  		&ncol,          /* Number of result columns written here */
  		&errorMessage          /* Error msg written here */
  	);

	// Clear the previous data values
	if(columnHeaders.size()<0) { columnHeaders.clear();  }
	if(columnData.size()<0)     { columnData.clear(); }

	// if the return value is okay, let's fill the data out
	if( retval == SQLITE_OK ){
		for(int i=0; i < ncol; ++i) {
  			columnHeaders.push_back(result[i]);   /* First row heading */
  		}
        	for(int i=0; i < ncol*nrow; ++i) {
  			columnData.push_back(result[ncol+i]);					
  		}
       	} else {
	       	// if there's an error, throw an exception
	       	throw SQLiteException(retval);
       	}

		// free the result*, because we don't need it anymore, and return the sqlite value
   	sqlite3_free_table(this->result);
		return retval;
}

// deconstructor just closes the database instance
SQLiteWrapper::~SQLiteWrapper(){
		#ifdef DEBUG
		Utility::LogMessage(_("Destroying SQLite wrapper."), M_INFO);
		#endif
		sqlite3_close(this->database);
}
